<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
 <head>
  <meta http-equiv="content-type" content="text/html; charset=UTF-8">
  <title>Generator syntax</title>

 </head>
 <body><div class="manualnavbar" style="text-align: center;">
 <div class="prev" style="text-align: left; float: left;"><a href="language.generators.overview.html">生成器</a></div>
 <div class="next" style="text-align: right; float: right;"><a href="class.generator.html">Generator objects</a></div>
 <div class="up"><a href="language.generators.html">生成器</a></div>
 <div class="home"><a href="index.html">PHP Manual</a></div>
</div><hr /><div id="language.generators.syntax" class="sect1">
  <h2 class="title">Generator syntax</h2>

  <p class="para">
   A generator function looks just like a normal function, except that instead
   of returning a value, a generator <a href="language.generators.syntax.html#control-structures.yield" class="link">yield</a>s as many values as it needs to.
  </p>

  <p class="para">
   When a generator function is called, it returns an object that can be
   iterated over. When you iterate over that object (for instance, via a
   <a href="control-structures.foreach.html" class="link">foreach</a> loop), PHP will call the generator function each time it needs a
   value, then saves the state of the generator when the generator yields a
   value so that it can be resumed when the next value is required.
  </p>

  <p class="para">
   Once there are no more values to be yielded, then the generator function
   can simply exit, and the calling code continues just as if an array has run
   out of values.
  </p>

  <blockquote class="note"><p><strong class="note">Note</strong>: 
   <p class="para">
    A generator cannot return a value: doing so will result in a compile
    error. An empty <strong class="command">return</strong> statement is valid syntax within
    a generator and it will terminate the generator.
   </p>
  </p></blockquote>

  <div class="sect2" id="control-structures.yield">
   <h3 class="title"><strong class="command">yield</strong> keyword</h3>

   <p class="para">
    The heart of a generator function is the <strong class="command">yield</strong> keyword.
    In its simplest form, a yield statement looks much like a return
    statement, except that instead of stopping execution of the function and
    returning, yield instead provides a value to the code looping over the
    generator and pauses execution of the generator function.
   </p>

   <div class="example" id="example-269">
    <p><strong>Example #1 A simple example of yielding values</strong></p>
    <div class="example-contents">
<div class="phpcode"><code><span style="color: #000000">
<span style="color: #0000BB">&lt;?php<br /></span><span style="color: #007700">function&nbsp;</span><span style="color: #0000BB">gen_one_to_three</span><span style="color: #007700">()&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;for&nbsp;(</span><span style="color: #0000BB">$i&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">1</span><span style="color: #007700">;&nbsp;</span><span style="color: #0000BB">$i&nbsp;</span><span style="color: #007700">&lt;=&nbsp;</span><span style="color: #0000BB">3</span><span style="color: #007700">;&nbsp;</span><span style="color: #0000BB">$i</span><span style="color: #007700">++)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #FF8000">//&nbsp;Note&nbsp;that&nbsp;$i&nbsp;is&nbsp;preserved&nbsp;between&nbsp;yields.<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">yield&nbsp;$i</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />}<br /><br /></span><span style="color: #0000BB">$generator&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">gen_one_to_three</span><span style="color: #007700">();<br />foreach&nbsp;(</span><span style="color: #0000BB">$generator&nbsp;</span><span style="color: #007700">as&nbsp;</span><span style="color: #0000BB">$value</span><span style="color: #007700">)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;echo&nbsp;</span><span style="color: #DD0000">"</span><span style="color: #0000BB">$value</span><span style="color: #DD0000">\n"</span><span style="color: #007700">;<br />}<br /></span><span style="color: #0000BB">?&gt;</span>
</span>
</code></div>
    </div>

    <div class="example-contents"><p>以上例程会输出：</p></div>
    <div class="example-contents screen">
<div class="cdata"><pre>
1
2
3
</pre></div>
    </div>
   </div>

   <blockquote class="note"><p><strong class="note">Note</strong>: 
    <p class="para">
     Internally, sequential integer keys will be paired with the yielded
     values, just as with a non-associative array.
    </p>
   </p></blockquote>

   <div class="caution"><strong class="caution">Caution</strong>
    <p class="para">
     If you use yield in an expression context (for example, on the right hand
     side of an assignment), you must surround the yield statement with
     parentheses. For example, this is valid:
    </p>

    <div class="informalexample">
     <div class="example-contents">
<div class="phpcode"><code><span style="color: #000000">
$data&nbsp;=&nbsp;(yield&nbsp;$value);</span>
</code></div>
     </div>

    </div>

    <p class="para">
     But this is not, and will result in a parse error:
    </p>

    <div class="informalexample">
     <div class="example-contents">
<div class="phpcode"><code><span style="color: #000000">
$data&nbsp;=&nbsp;yield&nbsp;$value;</span>
</code></div>
     </div>

    </div>

    <p class="para">
     This syntax may be used in conjunction with the
     <a href="class.generator.html#generator.send" class="link">send()</a> method on
     Generator objects.
    </p>
   </div>

   <div class="sect3" id="control-structures.yield.associative">
    <h4 class="title">Yielding values with keys</h4>

    <p class="para">
     PHP also supports associative arrays, and generators are no different. In
     addition to yielding simple values, as shown above, you can also yield a
     key at the same time.
    </p>

    <p class="para">
     The syntax for yielding a key/value pair is very similar to that used to
     define an associative array, as shown below.
    </p>

    <div class="example" id="example-270">
     <p><strong>Example #2 Yielding a key/value pair</strong></p>
     <div class="example-contents">
<div class="phpcode"><code><span style="color: #000000">
<span style="color: #0000BB">&lt;?php<br /></span><span style="color: #FF8000">/*&nbsp;The&nbsp;input&nbsp;is&nbsp;semi-colon&nbsp;separated&nbsp;fields,&nbsp;with&nbsp;the&nbsp;first<br />&nbsp;*&nbsp;field&nbsp;being&nbsp;an&nbsp;ID&nbsp;to&nbsp;use&nbsp;as&nbsp;a&nbsp;key.&nbsp;*/<br /><br /></span><span style="color: #0000BB">$input&nbsp;</span><span style="color: #007700">=&nbsp;&lt;&lt;&lt;'EOF'<br /></span><span style="color: #DD0000">1;PHP;Likes&nbsp;dollar&nbsp;signs<br />2;Python;Likes&nbsp;whitespace<br />3;Ruby;Likes&nbsp;blocks<br /></span><span style="color: #007700">EOF;<br /><br />function&nbsp;</span><span style="color: #0000BB">input_parser</span><span style="color: #007700">(</span><span style="color: #0000BB">$input</span><span style="color: #007700">)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;foreach&nbsp;(</span><span style="color: #0000BB">explode</span><span style="color: #007700">(</span><span style="color: #DD0000">"\n"</span><span style="color: #007700">,&nbsp;</span><span style="color: #0000BB">$input</span><span style="color: #007700">)&nbsp;as&nbsp;</span><span style="color: #0000BB">$line</span><span style="color: #007700">)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$fields&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">explode</span><span style="color: #007700">(</span><span style="color: #DD0000">';'</span><span style="color: #007700">,&nbsp;</span><span style="color: #0000BB">$line</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$id&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">array_shift</span><span style="color: #007700">(</span><span style="color: #0000BB">$fields</span><span style="color: #007700">);<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">yield&nbsp;$id&nbsp;</span><span style="color: #007700">=&gt;&nbsp;</span><span style="color: #0000BB">$fields</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />}<br /><br />foreach&nbsp;(</span><span style="color: #0000BB">input_parser</span><span style="color: #007700">(</span><span style="color: #0000BB">$input</span><span style="color: #007700">)&nbsp;as&nbsp;</span><span style="color: #0000BB">$id&nbsp;</span><span style="color: #007700">=&gt;&nbsp;</span><span style="color: #0000BB">$fields</span><span style="color: #007700">)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;echo&nbsp;</span><span style="color: #DD0000">"</span><span style="color: #0000BB">$id</span><span style="color: #DD0000">:\n"</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;echo&nbsp;</span><span style="color: #DD0000">"&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$fields</span><span style="color: #007700">[</span><span style="color: #0000BB">0</span><span style="color: #007700">]</span><span style="color: #DD0000">\n"</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;echo&nbsp;</span><span style="color: #DD0000">"&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$fields</span><span style="color: #007700">[</span><span style="color: #0000BB">1</span><span style="color: #007700">]</span><span style="color: #DD0000">\n"</span><span style="color: #007700">;<br />}<br /></span><span style="color: #0000BB">?&gt;</span>
</span>
</code></div>
     </div>

     <div class="example-contents"><p>以上例程会输出：</p></div>
     <div class="example-contents screen">
<div class="cdata"><pre>
1:
    PHP
    Likes dollar signs
2:
    Python
    Likes whitespace
3:
    Ruby
    Likes blocks
</pre></div>
     </div>
    </div>

    <div class="caution"><strong class="caution">Caution</strong>
     <p class="para">
      As with the simple value yields shown earlier, yielding a key/value pair
      in an expression context requires the yield statement to be
      parenthesised:
     </p>

     <div class="informalexample">
      <div class="example-contents">
<div class="phpcode"><code><span style="color: #000000">
$data&nbsp;=&nbsp;(yield&nbsp;$key&nbsp;=&gt;&nbsp;$value);</span>
</code></div>
      </div>

     </div>
    </div>
   </div>

   <div class="sect3" id="control-structures.yield.null">
    <h4 class="title">Yielding null values</h4>

    <p class="para">
     Yield can be called without an argument to yield a <strong><code>NULL</code></strong> value with an
     automatic key.
    </p>

    <div class="example" id="example-271">
     <p><strong>Example #3 Yielding <strong><code>NULL</code></strong>s</strong></p>
     <div class="example-contents">
<div class="phpcode"><code><span style="color: #000000">
<span style="color: #0000BB">&lt;?php<br /></span><span style="color: #007700">function&nbsp;</span><span style="color: #0000BB">gen_three_nulls</span><span style="color: #007700">()&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;foreach&nbsp;(</span><span style="color: #0000BB">range</span><span style="color: #007700">(</span><span style="color: #0000BB">1</span><span style="color: #007700">,&nbsp;</span><span style="color: #0000BB">3</span><span style="color: #007700">)&nbsp;as&nbsp;</span><span style="color: #0000BB">$i</span><span style="color: #007700">)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">yield</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />}<br /><br /></span><span style="color: #0000BB">var_dump</span><span style="color: #007700">(</span><span style="color: #0000BB">iterator_to_array</span><span style="color: #007700">(</span><span style="color: #0000BB">gen_three_nulls</span><span style="color: #007700">()));<br /></span><span style="color: #0000BB">?&gt;</span>
</span>
</code></div>
     </div>

     <div class="example-contents"><p>以上例程会输出：</p></div>
     <div class="example-contents screen">
<div class="cdata"><pre>
array(3) {
  [0]=&gt;
  NULL
  [1]=&gt;
  NULL
  [2]=&gt;
  NULL
}
</pre></div>
     </div>
    </div>
   </div>

   <div class="sect3" id="control-structures.yield.references">
    <h4 class="title">Yielding by reference</h4>

    <p class="para">
     Generator functions are able to yield values by reference as well as by
     value. This is done in the same way as
     <a href="functions.returning-values.html" class="link">returning references from functions</a>: 
     by prepending an ampersand to the function name.
    </p>

    <div class="example" id="example-272">
     <p><strong>Example #4 Yielding values by reference</strong></p>
     <div class="example-contents">
<div class="phpcode"><code><span style="color: #000000">
<span style="color: #0000BB">&lt;?php<br /></span><span style="color: #007700">function&nbsp;&amp;</span><span style="color: #0000BB">gen_reference</span><span style="color: #007700">()&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$value&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">3</span><span style="color: #007700">;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;while&nbsp;(</span><span style="color: #0000BB">$value&nbsp;</span><span style="color: #007700">&gt;&nbsp;</span><span style="color: #0000BB">0</span><span style="color: #007700">)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">yield&nbsp;$value</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />}<br /><br /></span><span style="color: #FF8000">/*&nbsp;Note&nbsp;that&nbsp;we&nbsp;can&nbsp;change&nbsp;$number&nbsp;within&nbsp;the&nbsp;loop,&nbsp;and<br />&nbsp;*&nbsp;because&nbsp;the&nbsp;generator&nbsp;is&nbsp;yielding&nbsp;references,&nbsp;$value<br />&nbsp;*&nbsp;within&nbsp;gen_reference()&nbsp;changes.&nbsp;*/<br /></span><span style="color: #007700">foreach&nbsp;(</span><span style="color: #0000BB">gen_reference</span><span style="color: #007700">()&nbsp;as&nbsp;&amp;</span><span style="color: #0000BB">$number</span><span style="color: #007700">)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;echo&nbsp;(--</span><span style="color: #0000BB">$number</span><span style="color: #007700">).</span><span style="color: #DD0000">'...&nbsp;'</span><span style="color: #007700">;<br />}<br /></span><span style="color: #0000BB">?&gt;</span>
</span>
</code></div>
     </div>

     <div class="example-contents"><p>以上例程会输出：</p></div>
     <div class="example-contents screen">
<div class="cdata"><pre>
2... 1... 0... 
</pre></div>
     </div>
    </div>
   </div>
  </div>
 </div><hr /><div class="manualnavbar" style="text-align: center;">
 <div class="prev" style="text-align: left; float: left;"><a href="language.generators.overview.html">生成器</a></div>
 <div class="next" style="text-align: right; float: right;"><a href="class.generator.html">Generator objects</a></div>
 <div class="up"><a href="language.generators.html">生成器</a></div>
 <div class="home"><a href="index.html">PHP Manual</a></div>
</div></body></html>
